package com.mikufufu.blog.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.mikufufu.blog.common.cache.RedisCache;
import com.mikufufu.blog.common.constant.ArticleType;
import com.mikufufu.blog.common.constant.RedisKey;
import com.mikufufu.blog.model.dto.admin.ArticleDTO;
import com.mikufufu.blog.model.dto.api.ArticleParam;
import com.mikufufu.blog.model.dto.admin.SearchArticleParam;
import com.mikufufu.blog.model.entity.ArticleTag;
import com.mikufufu.blog.model.entity.CollectionArticle;
import com.mikufufu.blog.model.vo.admin.ArticleVO;
import com.mikufufu.blog.model.vo.api.ArticleApiVO;
import com.mikufufu.blog.service.ArticleTagService;
import com.mikufufu.blog.service.CollectionArticleService;
import com.mikufufu.blog.utils.BeanUtil;
import com.mikufufu.blog.utils.StringUtils;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.mikufufu.blog.mapper.ArticleMapper;
import com.mikufufu.blog.model.entity.Article;
import com.mikufufu.blog.service.ArticleService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;

import java.util.*;

/**
 * 文章表 服务实现类
 * 
 */
@Slf4j
@Service
public class ArticleServiceImpl extends ServiceImpl<ArticleMapper, Article> implements ArticleService {

    @Autowired
    private ArticleTagService articleTagService;

    @Autowired
    private CollectionArticleService collectionArticleService;

    @Override
    public ArticleVO getArticleById(Integer id) {
        ArticleVO articleVO = baseMapper.getArticleById(id);
        if (StringUtils.isEmpty(articleVO)){
            return articleVO;
        }
        if (StringUtils.isEmpty(articleVO.getCollectionId())){
            articleVO.setType(ArticleType.NOMINAL);
            return articleVO;
        }
        // 如果是合集，则获取上一篇文章和下一篇文章
        articleVO.setType(ArticleType.COLLECTION);
        Map<String,ArticleVO> map = baseMapper.getPreAndNextArticle(articleVO.getId(),articleVO.getCollectionId());
        if (StringUtils.isEmpty(map)){
            return articleVO;
        }
        if (StringUtils.isNotEmpty(map.get("preArticle"))){
            log.debug("上一篇文章：《{}》",map.get("preArticle").getTitle());
            articleVO.setPreArticle(map.get("preArticle"));
        }
        if (StringUtils.isNotEmpty(map.get("nextArticle"))){
            log.debug("下一篇文章：《{}》",map.get("nextArticle").getTitle());
            articleVO.setNextArticle(map.get("nextArticle"));
        }
        return articleVO;
    }

    @Override
    public IPage<ArticleVO> getArticlePage(SearchArticleParam article) {
        List<Integer> tagIds = null;
        if (StringUtils.isNotBlank(article.getTagIds())){
            tagIds = StringUtils.toIntegerList(article.getTagIds());
        }
        return baseMapper.getArticlePage(article.getPage(), article,tagIds);
    }

    @Override
    public IPage<ArticleApiVO> getArticlePage(ArticleParam article) {
        return BeanUtil.copyPage(this.getArticlePage(BeanUtil.copy(article, SearchArticleParam.class)), ArticleApiVO.class);
    }

    @Override
    public ArticleVO getTopArticle() {
        return baseMapper.getTopArticle();
    }

    @Override
    public Boolean setTopArticle(Integer articleId) {
        return baseMapper.setTopArticle(articleId);
    }

    @Override
    public Long getWordCount() {
        return baseMapper.getWordCount();
    }

    @Override
    public boolean updateArticle(ArticleDTO article) {
        if (StringUtils.isNotBlank(article.getTagIds())) {
            List<Integer> tagIds = StringUtils.toIntegerList(article.getTagIds());
            // 明确查询所需字段（避免字段缺失导致NPE）
            List<ArticleTag> articleTags = articleTagService.list(new LambdaQueryWrapper<ArticleTag>().eq(ArticleTag::getArticleId, article.getId()));

            // 修正：检查空集合而非null（实际list()不会返回null）
            if (!articleTags.isEmpty()) {
                // 单次遍历同时收集待删除ID和已存在标签ID
                List<Integer> removeTagIds = new ArrayList<>();
                Set<Integer> existTagIdSet = new HashSet<>(); // 改用HashSet优化查找

                articleTags.forEach(articleTag -> {
                    if (tagIds.contains(articleTag.getTagId())) {
                        existTagIdSet.add(articleTag.getTagId()); // 正确使用tagId
                    } else {
                        removeTagIds.add(articleTag.getId());
                    }
                });

                // 执行批量删除
                if (!removeTagIds.isEmpty()) {
                    articleTagService.removeByIds(removeTagIds);
                }

                // 高效移除已存在的标签ID（O(n)复杂度）
                tagIds.removeIf(existTagIdSet::contains); // 利用Set的O(1)查找
            }

            // 构建新增列表（保留原逻辑）
            List<ArticleTag> addArticleTags = new ArrayList<>();
            for (Integer tagId : tagIds) { // 改用for-each更简洁
                ArticleTag articleTag = new ArticleTag();
                articleTag.setArticleId(article.getId());
                articleTag.setTagId(tagId);
                addArticleTags.add(articleTag);
            }

            // 批量插入前检查空列表
            if (!addArticleTags.isEmpty()) {
                articleTagService.saveBatch(addArticleTags);
            }
        }

        return this.updateById(BeanUtil.copy(article, Article.class));
    }

    @Override
    public Boolean addArticle(ArticleDTO article) {
        boolean flag = this.save(BeanUtil.copy(article, Article.class));
        RedisCache.set(RedisKey.ARTICLE_COUNT, this.count());
        RedisCache.set(RedisKey.WORD_COUNT, baseMapper.getWordCount());
        List<Integer> tagIds = StringUtils.toIntegerList(article.getTagIds());
        List<ArticleTag> articleTags = new ArrayList<>();
        tagIds.forEach(tagId -> {
            ArticleTag articleTag = new ArticleTag();
            articleTag.setArticleId(article.getId());
            articleTag.setTagId(tagId);
            articleTags.add(articleTag);
        });
        articleTagService.saveBatch(articleTags);
        // 如果是合集文章，则保存合集文章关联表
        if (ArticleType.COLLECTION.equals(article.getType()) && StringUtils.isNotEmpty(article.getCollectionId())) {
            Integer collectionId = article.getCollectionId();
            CollectionArticle collectionArticle = new CollectionArticle();
            collectionArticle.setCollectionId(collectionId);
            collectionArticle.setArticleId(article.getId());
            long count = collectionArticleService.count(new LambdaQueryWrapper<CollectionArticle>().eq(CollectionArticle::getCollectionId, collectionId));
            collectionArticle.setOrderNum((int) (count + 1));
            collectionArticleService.save(collectionArticle);
        }
        return flag;
    }
}
